package day_04_03_JUCAssistClass;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author shihan
 * @Date 2020/11/1 16:11
 * @Version 1.0
 */
public class SemaphoreDemo {

    /**
     *【Semaphore 信号量】
     * 1、new Semaphore(int permits) 实例化时，定义好有几个"空车位"资源
     * 2、Semaphore.acquire() 当信号量中资源个数不为零时，当前线程可以执行，并且信号量数值 减一；
     * 3、当信号量中资源个数为零时，当前线程被阻塞；
     * 4、当抢占到信号量数值的线程，执行完毕后，调用完 Semaphore.release() ，信号量数值 加一，并唤醒其他被阻塞的线程；
     * PS：目前只是初步理解，底层源码还有待深入学习--例如底层用的是 notify、wait 来实现的，还是 lock.signal()、lock.await() 来实现的；
     *【Semaphore 应用场景】
     * 1、互斥资源 的访问；
     * 2、控制 多线程并发的线程数；
     * @param args
     */
    public static void main(String[] args) {

        Semaphore semaphore = new Semaphore(3);     //有三个车位

        for (int i = 1; i <= 7 ; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();    //信号量不为零，抢占到资源，当前线程可以执行，并且 信号量数值 减一；信号量为 0，当前线程被阻塞；
                    System.out.println(Thread.currentThread().getName() + "\t" + "抢占了车位！");
                    //占着车位 2 秒
                    try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }

                    System.out.println(Thread.currentThread().getName() + "\t" + "离开了车位！");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //线程执行完毕，信号量数值 加一，唤醒其他被阻塞的线程
                    semaphore.release();
                }
            },i + "").start();
        }
    }
}
